//
// Created by ych on 2/13/24.
//
#include "reader.h"
#include "../machine/ych_state.h"

#define FILE_BUFFER 1024

void initReader1(Reader *reader, YState *y_state) {
    reader->y_state = y_state;
    initString(&reader->file_text);
    reader->ch = reader->file_text.data;
    reader->pos = 0;
    reader->line = 1;
    reader->line_start_pos = 0;
}

void initReader2(Reader *reader, YState *y_state, char *file_path) {
    reader->y_state = y_state;
    reader->file_path = file_path;
}

void rollbackReader(Reader *reader){
    freeYString(&reader->file_text);
    initString(&reader->file_text);
    reader->ch = reader->file_text.data;
    reader->pos = 0;
    reader->line = 1;
    reader->line_start_pos = 0;
}
void freeReader(Reader *reader) {
    reader->y_state = NULL;
    reader->file_path = NULL;
    freeYString(&reader->file_text);
}

void readerThrow(Reader *reader) {
    Error error;
    error.code = EXCEPTION_FILENOTFOUND;
    copyString(&error.info, "FILE NOT FOUND path:");
    appendString(&error.info, reader->file_path);
    pushErrorStack(&reader->y_state->errors, error);
}

void readLine(Reader *reader, char *buffer) {
    appendString(&reader->file_text, buffer);
    reader->ch = reader->file_text.data + reader->pos;
}

void readFile(Reader *reader) {
    FILE *file;
    char buffer[FILE_BUFFER];
    initString(&reader->file_text);
    file = fopen(reader->file_path, "r");
    if (file == NULL) {
        readerThrow(reader);
        throw(EXCEPTION_FILENOTFOUND);
    }

    while (fgets(buffer, sizeof(buffer), file) != NULL) {
        appendString(&reader->file_text, buffer);
    }
    fclose(file);
    reader->ch = reader->file_text.data;
    reader->pos = 0;
    reader->line = 1;
    reader->line_start_pos = 0;
}

char getChar(Reader *reader) {
    return *reader->ch;
}

void nextChar(Reader *reader) {
    if (*(reader->ch - 1) == '\n') {
        reader->line_start_pos = reader->pos;
        reader->line++;
    }
    reader->pos++;
    reader->ch++;
}

void toStatementEnd(Reader *reader) {
    while (*reader->ch != ';' && *reader->ch != '\0') {
        nextChar(reader);
    }
}